package com.example.netcamerastreamdemo;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.View;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;

import static android.media.MediaFormat.KEY_HEIGHT;
import static android.media.MediaFormat.KEY_WIDTH;
import static android.media.MediaFormat.MIMETYPE_VIDEO_AVC;

public class DecodeLocalMp4Activity extends AppCompatActivity {
    private static final String TAG = "DecodeLocalMp4Activity";

    MediaExtractor mediaExtractor;
    MediaFormat mediaFormat;
    MediaCodec mediaCodec;
    SurfaceView surfaceView;
    boolean isDecodeFinish = false;
    DecoderMP4Thread decoderMP4Thread = new DecoderMP4Thread();

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        surfaceView = findViewById(R.id.surface_view);

        requestPermissions(new String[]{
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        }, 0);

        Log.i(TAG, "---" + getExternalFilesDir(null));
    }

    private void initMediaCodec(){
        try {
            mediaCodec = MediaCodec.createDecoderByType("video/avc");
        } catch (IOException e) {
            e.printStackTrace();
        }
        mediaFormat = MediaFormat.createVideoFormat("video/avc", 1080, 2280);

        Surface surface = surfaceView.getHolder().getSurface();

        //必须配置一个surface,作为其输出解码显示画面
        mediaCodec.configure(mediaFormat, surface, null, 0);
        mediaCodec.start();

        decoderMP4Thread.start();
    }

    /**
     *  Play the MP4 file Thread
     */
    private class DecoderMP4Thread extends Thread {
        long pts = 0;
        FileInputStream fileInputStream;
        File file;
        int count = 0;
        @Override
        public void run() {
            super.run();
            String path = getExternalFilesDir(null)+ "/MV/flvtest.flv";
//            String path = getExternalFilesDir(null)+ "/1623288807379.h264";
//        String path = getExternalFilesDir(null)+ "/record.mp4";

            try {
                file = new File(path);
                Log.i(TAG, "---file===" + file.length());

                fileInputStream = new FileInputStream(file);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            while (!isDecodeFinish) {
                int inputIndex = mediaCodec.dequeueInputBuffer(1000);
                Log.i(TAG, "inputIndex: " + inputIndex);
                if (inputIndex >= 0) {
                    ByteBuffer byteBuffer = mediaCodec.getInputBuffer(inputIndex);
                    //读取一片或者一帧数据
//                    int sampSize = mediaExtractor.readSampleData(byteBuffer,0);

                    byteBuffer.clear();
                    byte[] bytes = new byte[1000];
                    try {
                        fileInputStream.read(bytes, count * 1000, 1000);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    count++;
                    byteBuffer.put(bytes);
                    //读取时间戳
//                    long time = mediaExtractor.getSampleTime();
//                    Log.i(TAG, "sampSize: " + sampSize + "time: " + time);
//                    if (sampSize > 0 && time > 0) {
                    mediaCodec.queueInputBuffer(inputIndex, 0, bytes.length, 0, 0);
                    //读取一帧后必须调用，提取下一帧
//                        mediaExtractor.advance();
                    //控制帧率在30帧左右
                    try {
                        sleep(30);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
//                    }

                }
                MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                int outIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 1000);
                Log.i(TAG, "outIndex: " + outIndex);
                if (outIndex >= 0) {
                    mediaCodec.releaseOutputBuffer(outIndex, true);
                }
            }
        }

    }

    public void close() {
        if (mediaCodec != null) {
            mediaCodec.stop();
            mediaCodec.release();
            isDecodeFinish=true;
        }
    }

    private class DecodeThread extends Thread{
        private MediaCodec decoder;
        private int mWidth = 640;
        private int mHeight = 480;
        private int decodeCount = 0;
        private MediaFormat outFormat;
        File file;
        FileInputStream fileInputStream;

        @Override
        public void run() {
            while (decodeCount == 0){
//                String path = getExternalFilesDir(null)+ "/MV/flvtest.flv";
            String path = getExternalFilesDir(null)+ "/1623288807379.h264";
//            String path = getExternalFilesDir(null)+ "/record.mp4";

                try {
                    file = new File(path);
                    Log.i(TAG, "---file===" + file.length());
                    fileInputStream = new FileInputStream(file);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                runDecode();
            }
        }

        private void runDecode(){
            if (decoder == null){
                try {
                    MediaFormat format = MediaFormat.createVideoFormat(MIMETYPE_VIDEO_AVC, mWidth, mHeight);
                    decoder = MediaCodec.createDecoderByType(MIMETYPE_VIDEO_AVC);
                    decoder.configure(format, surfaceView.getHolder().getSurface(), null, 0);
                    decoder.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            while (true){
                byte[] frameByte = new byte[10000];
                Log.i(TAG, "---decodeCount===" + decodeCount);
                try {
                    fileInputStream.read(frameByte);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                int inputIndex = decoder.dequeueInputBuffer(10000);
                if (inputIndex >= 0){
                    ByteBuffer byteBuffer = decoder.getInputBuffer(inputIndex);
                    byteBuffer.put(frameByte);
                    decoder.queueInputBuffer(inputIndex, 0, frameByte.length, 0, 0);
                }
                MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                int outputIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
                if (outputIndex >= 0){
                    decoder.releaseOutputBuffer(outputIndex, true);
                }
//                if (outFormat == null) {
//                    outFormat = decoder.getOutputFormat();
//                    Log.i(TAG, "---outFormat===" + outFormat.toString());
//                    Log.i(TAG, "---outFormat=KEY_WIDTH==" + outFormat.getInteger(KEY_WIDTH));
//                    Log.i(TAG, "---outFormat=KEY_HEIGHT==" + outFormat.getInteger(KEY_HEIGHT));
////                    mSurfaceView.getHolder().setFixedSize(outFormat.getInteger(KEY_WIDTH));
//                }

//                try {
//                    Thread.sleep(500);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                decodeCount++;
            }
        }

        private void stopLopper(){
            decoder.reset();
            decoder.release();
            decodeCount = -1;
        }
    }

    public void test1(View view){

        mediaExtractor = new MediaExtractor();
        //设置MP4文件存放的位置
//        String path = getExternalFilesDir(null)+ "/1623288807379.h264";
//        String path = getExternalFilesDir(null)+ "/record.mp4";
        String path = getExternalFilesDir(null)+ "/MV/flvtest.flv";
        try {
            mediaExtractor.setDataSource(path);

        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.i(TAG, "getTrackCount: " + mediaExtractor.getTrackCount());
        for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
            MediaFormat format = mediaExtractor.getTrackFormat(i);
            String mime = format.getString(MediaFormat.KEY_MIME);
            Log.i(TAG, "---mime===" + mime);
            //如果是video格式
            if (mime.startsWith("video")) {
                mediaFormat = format;
                mediaExtractor.selectTrack(i);
            }
        }
        new DecodeThread().start();
//        initMediaCodec();
    }
}